<?php
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	 *
	 *	Autocredit
	 *	Copyright (C) 2012, Brent Flap <blog.cyberdevil.nl>
	 *
	 *	This file is part of Autocredit.
	 *
	 *	Autocredit is free software: you can redistribute it and/or modify
	 *	it under the terms of the GNU General Public License as published by
	 *	the Free Software Foundation, either version 3 of the License, or
	 *	any later version.
	 *
	 *	This program is distributed in the hope that it will be useful,
	 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
	 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	 *	GNU General Public License for more details.
	 *
	 *	You should have received a copy of the GNU General Public License
	 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
	 *
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	// Config
	define('PATH',"./plugins/");
	class Plugins{
		static private $Plugins = array();
		static public $Proxies = "NOT_SET_YET";
		static private $DeadProxies = array();
		function __construct(){
			message("Plugin handler loaded.","NOTICE");
			if($handle = opendir(PATH))
				while (false !== ($file = readdir($handle))) {
					if(is_dir(PATH . $file) && $file != "." && $file != ".."){
						if(file_exists( PATH . $file . "/" . $file . ".php" )){
							Plugins::$Plugins[$file] = false;
							Plugins::register(PATH . $file . "/$file.php");
						}
					}
				}
		}
		static function enablePlugin($plugin){
			self::$Plugins[$plugin] = true;
		}
		static function register($path){
			message("Plugin: " . $path . " registered","NOTICE");
			require_once($path);
		}
		static function hook($event){
			foreach(Plugins::$Plugins as $Plugin => $Enabled){
				if(method_exists($Plugin,$event)){
					if($Enabled == true){
						message("Plugin: " . $Plugin . " -> event: $event loaded.","NOTICE");
						if(!call_user_func(array($Plugin,$event))){
							throw new Exception(message("Cannot hook","ERROR"));
						}
					}
				}
			}
		}
		static function getIDs($file){
			$contents = array();
			if(file_exists("data/".$file) && filesize("data/".$file) > 0){
				$handle = fopen("data/".$file, "r");
				$contents = fread($handle, filesize("data/".$file));
				fclose($handle);
				$contents = explode("\n",$contents);
			}
			return $contents;
		}
		static function addID($file,$id){ 
			$fp = fopen("data/".$file, 'a+');
			fwrite($fp, $id."\n");
			fclose($fp);
		}
		static function saveIMG($url,$path){
			$image = self::getPage($url);
			$filename = end(explode("/", $url));
			if (!file_exists($path.$filename)){
				if (!$handle = fopen($path.$filename, 'a')) {
					message("Cannot open file ($filename)","ERROR");
				}
				if (fwrite($handle, $image) === FALSE) {
					message("Cannot write to file ($filename)","ERROR");
				}
				fclose($handle);
			}
			else{
				message("$filename already exists.","WARNING");
			}
		}
		static function Parse($pattern, $content, $matchid){
		    preg_match($pattern, $content, $output);
		    if(isset($output[$matchid])){return $output[$matchid];}
		    else{return $output[$matchid]=NULL;}
		    
		}
		static function finalURL($url,$id){
			return str_replace("{id}",$id,$url);
		}
		static function getProxies($file){
			if(file_exists($file)){
				$handle = fopen($file,'r');
				if(filesize($file)>0){
					$content = fread($handle,filesize($file));
					$self->Proxies = explode("\n",$content);
					fclose($handle);
					return $self->Proxies;
				}
				else{
					message("Proxy file ($file) is empty.","ERROR");
				}
				fclose($handle);
			}
			else{
				message("Proxy file ('$file') doesn't exist.","ERROR");
			}
		}
		static function removeProxy($proxy){
			$temp = self::$Proxies;
			unset(self::$Proxies); // I know this doesn't work 'cause it's a static object.
			foreach($temp as $k => $v){
				if($v != $proxy){
					self::$Proxies[] = $v;
				}
			}
			return true;
		}
		static function getRandomProxy($Proxies){
			$trigger = false;
			$random = "";
			if(count(self::$Proxies)-1 == count(self::$DeadProxies)){
				message("All proxies are labled as dead.", "ERROR");
				die();
			}
			while($trigger==false){
				$random = rand(0,count($Proxies)-1);
				if(!in_array($Proxies[$random],self::$DeadProxies) && $Proxies[$random] !=""){
					$trigger = true;
				}
			}
			return $Proxies[$random];
		}
		static function getPage($url,$options = null,$t = 0,$failcount = 0){
			$ch = curl_init(); // create a new cURL resource
			curl_setopt($ch, CURLOPT_URL, $url); // set URL and other appropriate options
			curl_setopt($ch, CURLOPT_HEADER, false);
			global $use_proxy,$proxy_list,$page_timeout,$user_agent,$maxfails;
			if($use_proxy){
				$proxy = "";
				if(self::$Proxies == "NOT_SET_YET"){
					self::$Proxies = self::getProxies($proxy_list);
					$proxy = self::getRandomProxy(self::$Proxies);
				}
				else{
					$proxy = self::getRandomProxy(self::$Proxies);
				}
				if($t == 1){
					message("Retrying $url with proxy $proxy","WARNING");
				}
				curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
				curl_setopt($ch, CURLOPT_PROXY, $proxy);
			}
			else{
				curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 0);
				curl_setopt($ch, CURLOPT_PROXY, null);
			}
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_TIMEOUT, $page_timeout);
			curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);	
			
			
			if($options!=null){ // Let plugins overrule the default options by using the $options var.
				curl_setopt_array($ch, $options);
			}
			
			
			if(!$result = curl_exec($ch)){ // grab URL and pass it to the var $result
				if($use_proxy){
					$error = curl_error($ch);
					message("Proxy: ".$proxy."   ".$url." ".curl_error($ch),"ERROR");
					$proxyDeadMessages = array(
						"Proxy CONNECT aborted",
						"Received HTTP code 403 from proxy after CONNECT",
						"Received HTTP code 500 from proxy after CONNECT",
						"Received HTTP code 502 from proxy after CONNECT",
						"Received HTTP code 503 from proxy after CONNECT",
						"Received HTTP code 405 from proxy after CONNECT",
						"Received HTTP code 400 from proxy after CONNECT",
						"Received HTTP code 307 from proxy after CONNECT",
						"Received HTTP code 301 from proxy after CONNECT",
						"Received HTTP code 0 from proxy after CONNECT",
						"Proxy CONNECT aborted due to timeout",
						"connect() timed out!",
						"Operation timed out after 60000 milliseconds with 0 bytes received",
						"couldn't connect to host",
						"Received HTTP code 404 from proxy after CONNECT",
						"Couldn't resolve proxy",
						"Recv failure: Connection reset by peer"
					);
					foreach($proxyDeadMessages as $dm){
						if($error == $dm){
							self::$DeadProxies[] = $proxy;
							message("Labled proxy: $proxy as dead.","WARNING");
						}
					}
				}
				else{
					message($url." ".curl_error($ch),"ERROR");
				}
				if($failcount < $maxfails){
					$failcount++;
					self::getPage($url,$options,$t,$failcount);
				}
			}
			else if($use_proxy){
				message("Using proxy: ".$proxy." for: ".$url." ".curl_getinfo($ch, CURLINFO_HTTP_CODE),"NOTICE");
			}
			curl_close($ch); // close cURL resource, and free up system resources
			return $result;
		}
	}
?>
